#include <iostream>
#include <vector>
#include <queue>

int direct_vec[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

bool check(std::vector<std::vector<int>> &sq_map, int v)
{
    int r = sq_map.size();
    int c = sq_map[0].size();
    std::vector<std::vector<bool>> vis_map(r, std::vector<bool>(c, false));

    if (sq_map[0][0] < v)
        return false;

    std::queue<std::pair<int, int>> q;
    q.push({0, 0});
    vis_map[0][0] = true;

    while (!q.empty())
    {
        auto p = q.front();
        q.pop();

        for (int i = 0; i < 4; i++)
        {
            int x = p.first + direct_vec[i][0];
            int y = p.second + direct_vec[i][1];
            if (x >= 0 && x < c && y >= 0 && y < r && !vis_map[y][x] && sq_map[y][x] >= v)
            {
                q.push({x, y});
                vis_map[y][x] = true;
            }
        }
    }

    return vis_map[r - 1][c - 1];
}

int main()
{
    int R, C;
    std::cin >> R;
    std::cin >> C;

    std::vector<std::vector<int>> sq_map(R, std::vector<int>(C));
    int min_val = 1e5;
    int max_val = 0;
    for (int i = 0; i < R; i++)
    {
        for (int j = 0; j < C; j++)
        {
            int sig;
            std::cin >> sig;
            sq_map[i][j] = sig;
            min_val = std::min(min_val, sig);
            max_val = std::max(max_val, sig);
        }
    }

    std::cout << min_val << " " << max_val << std::endl;
    int l = min_val;
    int r = max_val;
    int res = min_val;
    while (l <= r)
    {
        int mid = (l + r) / 2;
        if (check(sq_map, mid))
        {
            res = mid;
            l = mid + 1;
        }
        else
        {
            r = mid - 1;
        }
    }

    std::cout << res << std::endl;
    return 0;
}